﻿using System;
using System.Text;
using HK.Core.Encryption.Protocol;
using HK.Core.Extend;
using HK.Core.IO.Output;
using HK.Core.Serializable;
using HK.Core.Serializable.Attribute;
using HK.Core.Serializable.Data;
using HK.Core.Serializable.Protocol.Data;
using HK.Core.Utils;
using HK.Editor.Utils;
using UnityEngine;
using HLogger = HK.Core.Logs.Logger;

namespace HK.Editor.Serializable
{
    /// <summary>
    /// 序列化资产文件
    /// </summary>
    /// <typeparam name="TAsset">序列化资产文件类型</typeparam>
    /// <typeparam name="TBody">资产文件Body数据类型</typeparam>
    [Serializable]
    public class SEAsset<TAsset, TBody> : SAsset, ISAsset<TBody>
        where TAsset : SAsset
        where TBody : SAssetData, new()
    {

        #region Static

        private static TAsset _instance = default(TAsset);

        /// <summary>
        /// 实例
        /// </summary>
        public static TAsset Instance
        {
            get
            {
                if (default(TAsset) != _instance) return _instance;
                _instance = UtilsSEAssets.LoadAssetSync<TAsset>();
                if (string.IsNullOrEmpty(_instance.CheckCode))
                {
                    HLogger.Error($"{typeof(TAsset).Name}::校验码生成失败!");
                }
                return _instance;
            }
        }

        #endregion
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        /// <param name="iStatic">静态文件标志位</param>
        /// <param name="iCreateTime">创建时间</param>
        protected SEAsset(bool iStatic, long iCreateTime = 0L) : base(iStatic, true, iCreateTime) { }
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        private SEAsset() { }
        
        #region Data

        [SerializeField, SBody("设定")]
        private TBody body = new TBody();
        /// <summary>
        /// 序列化数据 - Body
        /// </summary>
        public TBody Body => body;

        #endregion

        #region CheckCode

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        public override string GenCheckCode(CheckMode iMode = CheckMode.Md5)
        {
            Header.Refresh();
            return UtilsCheckCode.Encode(header, iMode, false);
        }

        #endregion

        #region Operation

        /// <summary>
        /// Json相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected override void DoJsonOperateOptions(int iOptions, string iSecretKey = null)
        {
            // 导入 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                jsonFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(jsonFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                jsonFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                var dirty = jsonFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }
        
        /// <summary>
        /// Token相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected override void DoTokenOperateOptions(int iOptions, string iSecretKey = null)
        {
            
            // 导入 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }

        #region Clear

        /// <summary>
        /// 清除
        /// </summary>
        /// <param name="iOptions">选项</param>
        /// <param name="iForce">强制清空标志位</param>
        public override void Clear(int iOptions, bool iForce = false)
        {
            // 清空
            if(UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.Clear))
            {
                Body?.Clear();
                return;
            }
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                DoJsonOperateOptions(iOptions);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                DoTokenOperateOptions(iOptions);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                this.Warning("Import():尚未支持二进制强制清空, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return;
            this.Error("Clear():Unknown Operation Options:{0}", iOptions);
        }

        #endregion

        #endregion
        
    }
}